class OptimizedLRUCache {
  constructor(capacity = 100) {
    this.capacity = capacity;
    this.cache = new Map();
    this.accessMap = new Map();
    this.head = Symbol('head');
    this.tail = Symbol('tail');
    this.accessMap.set(this.head, { next: this.tail });
    this.accessMap.set(this.tail, { prev: this.head });
  }

  get(key) {
    if (!this.cache.has(key)) return null;

    this._refreshAccess(key);
    return this.cache.get(key).value;
  }

  set(key, value, ttl = Infinity) {
    if (this.cache.size >= this.capacity) {
      this._evict();
    }

    this.cache.set(key, {
      value,
      expireAt: Date.now() + ttl,
    });
    this._refreshAccess(key);
  }

  _refreshAccess(key) {
    if (this.accessMap.has(key)) {
      this._removeNode(key);
    }
    this._addToTail(key);
  }

  _evict() {
    const lruKey = this.accessMap.get(this.head).next;
    this.cache.delete(lruKey);
    this._removeNode(lruKey);
  }

  _removeNode(key) {
    const node = this.accessMap.get(key);
    node.prev.next = node.next;
    node.next.prev = node.prev;
    this.accessMap.delete(key);
  }

  _addToTail(key) {
    const last = this.accessMap.get(this.tail).prev;
    this.accessMap.set(key, { prev: last, next: this.tail });
    last.next = key;
    this.accessMap.get(this.tail).prev = key;
  }
}
